<?php
/**
 * food category information
 */
class food_category_model extends CI_Model {
    private $error = array();
    private $is_valid_schema = false;
	/**
	 * constructor to pre load database object
	 */
    public function __construct()
	{
		parent::__construct();
		$this->load->database();
	}

    /**
     * @param int $size
     * @param int $offset
     * @param bool $encode_html
     * 
     * @return array categories
     */
	public function get_category($size=9999, $offset=0, $encode_html = true)
	{
		$categories = array();
		$this->db->order_by("sequence", "id");
		/**
		 * if size is set, then apply it to the query, else get all food categories
		 */
	    $this->db->limit($size, $offset);

		//----------------------------------------------------------------------
		$query = $this->db->get('food_category');
		foreach ($query->result_array() as $row)
		{
            if($encode_html){
                $row['en_name'] = htmlentities($row['en_name'], ENT_QUOTES, "UTF-8");
                $row['ch_name'] = htmlentities($row['ch_name'], ENT_QUOTES, "UTF-8");
            }
    		$categories[$row['sequence']] = $row;
		}
		return $categories;
	}

    /**
     * create a new food category in database
     *
     * @param string $en_name
     * @param string $ch_name
     * @param string $sequence
     *
     * @return array error
     */
	public function create($en_name, $ch_name, $sequence)
	{
        $this->error = array('user' => array(), 'system' => array());

        //prepare data for validation and create
        $en_name = trim($en_name);
        $ch_name = trim($ch_name);
        $sequence = trim($sequence);
        //unique sequence check
        $condition = "sequence = '" . mysql_real_escape_string($sequence) . "'";
        if($this->_hit_count($condition) > 0){
            $this->error['user']['create_action'] = 'food category already exist with same sequence';
            return $this->error;
        }

		$this->_validate_schema($en_name, $ch_name, $sequence);
		if(true === $this->is_valid_schema){
            $data =  array(
                'en_name' => $en_name,
                'ch_name' => $ch_name,
                'sequence' => $sequence
            );
            $this->db->insert('food_category', $data);
        }
        return $this->error;
	}

    /**
     * get single category information
     *
     * @param int $id
     * @param bool $encode_html
     * @return array category
     */
	public function read($id, $encode_html = true)
	{
        $this->db->limit(1);
		$this->db->where('id', $id);
		$query = $this->db->get('food_category');
		$result = $query->row_array();

        if($encode_html){
            foreach($result as $key => $value){
                $result[$key] = htmlentities($value, ENT_QUOTES, "UTF-8");
            }
        }
        return $result;
	}

    /**
     * update category
     *
     * @param string $id
     * @param string $en_name
     * @param string $ch_name
     * @param string $sequence
     *
     * @return array error
     */
	public function update($id, $en_name, $ch_name, $sequence)
	{
        $this->error = array('user' => array(), 'system' => array());
        
        /**
         * check database integrity in development
         */
        $condition = "id = '" . mysql_real_escape_string($id) . "'";
        if($this->_hit_count($condition) != 1){
            $this->error['system']['update_query'] = "update query hit is not exactly 1 row";
        }

        //prepare data for validation and update
        $en_name = trim($en_name);
        $ch_name = trim($ch_name);
        $sequence = trim($sequence);

        //unique sequence check, it is okay to update with same sequence the row it updated agsint  
        $category = $this->read($id);
        $condition = "sequence = '" . mysql_real_escape_string($sequence) . "'";
        if($this->_hit_count($condition) > 0 && $category['sequence'] !== $sequence){
            $this->error['user']['update_action'] = 'food category already exist with same sequence';
            return $this->error;
        }

        $this->_validate_schema($en_name, $ch_name, $sequence);
		if(true === $this->is_valid_schema){
            $data =  array(
                'en_name' => $en_name,
                'ch_name' => $ch_name,
                'sequence' => $sequence
            );
            $this->db->where('id', $id);
            $this->db->update('food_category', $data);
        }
        return $this->error;
	}

    /**
     * delete category
     *
     * @param string $id
     *
     * @return array error
     */
	public function delete($id)
	{
        $this->error = array('user' => array(), 'system' => array());
        /**
         * check database integrity in development, put in system error array
         */
        $condition = "id = '" . mysql_real_escape_string($id) . "'";
        if($this->_hit_count($condition) !== 1){
            $this->error['system']['delete_query'] = 'delete query hit is not exactly 1 row';
        }

        // check if there are food under this category, if yes, dont delete category until user delete food first
        $this->load->model('food_model', 'food');
        $food = $this->food->get_food($id);
        if(count($food) > 0){
            $this->error['user']['delete_non_empty_category'] = 'you try to delete category that still have food';
            return $this->error;
        }

        // ready to proceeding delete
		$this->db->where('id', $id);
		$this->db->delete('food_category');
        return $this->error;
	}
    /**
     * @throws Exception
     * @param $from_id
     * @param $to_id
     * @return array errors
     */
    public function swap($from_id, $to_id)
    {
        $this->error = array('user' => array(), 'system' => array());

        // prepare data
        $from_id = trim($from_id); $to_id = trim($to_id);

        // if in same place
        if($from_id === $to_id){
            $this->error['user']['swap_sql'] = "swap between same place disallowed";
            return $this->error;
        }
        // if in difference palce but have multiple hits, system tampered
        $condition = "id = '" . mysql_real_escape_string($from_id) . "'";
        $from = $this->_hit_count($condition);
        $condition = "id = '" . mysql_real_escape_string($to_id) . "'";
        $to = $this->_hit_count($condition);

        if($from !== 1 && $to !== 1){
            $this->error['system']['swap_query'] = 'swap query result in more than 2 rows, check database integrity';
        }

        // ready for swap now, get sequence (above tests ensure one hit)
        $from_category = $this->read($from_id);
        $to_category = $this->read($to_id);
        $this->db->where('id', $from_id);
        $this->db->update('food_category', array('sequence' => $to_category['sequence']));
        $this->db->where('id', $to_id);
        $this->db->update('food_category', array('sequence' => $from_category['sequence']));

        return $this->error;
    }

    /**
     * helper to determine how many rows exists in database with certain conditions
     * @param string $condition
     * @return int
     */
    private function _hit_count($condition){
        $result = $this->db->query("SELECT * FROM `food_category` WHERE " . $condition);
        return $result->num_rows();
    }
    /**
     * helper validate against table schema
     *
     * @param string $en_name
     * @param string $ch_name
     * @param string $sequence
     *
     * @return void
     */
    private function _validate_schema($en_name, $ch_name, $sequence){
        // reset schema valid indicater
        $this->is_valid_scehma = false;
        $this->load->library('validation/validation_string');

        $user_error_intro_count = count($this->error['user']);

        // en_name 0 - 64 chars
        $this->validation_string->set_data($en_name)->max_length(64)->min_length(1);
        if(false === $this->validation_string->result()){
            $this->error['user']['en_name'] = "en name should have 1 - 64 characters";
		}

        // ch_name less than 64 chars
        $this->validation_string->set_data($ch_name)->max_length(64)->min_length(1);
        if(false === $this->validation_string->result()){
            $this->error['user']['ch_name'] = "ch name should have 1 - 64 characters";
		}

        // sequence less than 8 chars, in format combine digit and '-'
        $this->validation_string->set_data($sequence)->is_sequence();
        if(false === $this->validation_string->result()){
            $this->error['user']['sequence'] = "sequence should less than 8 chars, in format combine digit and - ";
		}

        $user_error_outro_count = count($this->error['user']);

        if($user_error_intro_count === $user_error_outro_count){
            $this->is_valid_schema = true;
        }
    }
}

/* End of file food_category_model.php */
/* Location: ./system/application/models/food_category_model.php */